<?php
/**
 * Created by PhpStorm.
 * User: zhanglihe
 * Date: 17/11/2
 * Time: 下午2:33
 */
namespace App;

use App\Models\SmsLog;
use Carbon\Carbon;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\Log;

class Sms
{
    /**
     * 短信验证
     *
     * 模板内容：验证码${code}，您正在进行身份验证，打死不要告诉别人哦！
     */
    const TPL_CHECK_CODE = 'SMS_169955077';

    /**
     * 登录确认验证码
     * 模板内容：验证码${code}，您正在登录，若非本人操作，请勿泄露。
     */
    const TPL_LOGIN = 'SMS_169955076';

    /**
     * 用户注册验证码
     * 模板内容：验证码${code}，您正在注册成为新用户，感谢您的支持！
     */
    const TPL_REGISTER = 'SMS_169955074';

    /**
     * 修改改码验证码
     * 模板内容：验证码${code}，您正在尝试修改登录密码，请妥善保管账户信息。
     */
    const TPL_CHANGE_PASSWORD = 'SMS_169955073';

    /**
     * 充值成功通知
     * 模板内容：您的尾号${card_no}油卡充值${amount}元已到账，请及时查看圈存
     */
    const TPL_RECHARGE_SUCCESS = 'SMS_171111784';

    /**
     * 充值失败
     * 内容：订单ID:${order_id}油卡充值失败，请登录后台查看详情并处理
     */
    const TPL_RECHARGE_FAIL = 'SMS_167972452';


    /** 短信签名*/
    const SIGN_NAME  = '油惠侠';

    public static $cachePrefix = '__VC__';
    public static $tplName = [
        self::TPL_CHECK_CODE => 'sms verify',
        self::TPL_LOGIN => 'login',
        self::TPL_REGISTER => 'register',
        self::TPL_CHANGE_PASSWORD => 'edit password',
        self::TPL_RECHARGE_SUCCESS => 'recharge success',
        self::TPL_RECHARGE_FAIL => 'recharge fail',
    ];

    /**
     * 验证码
     *
     * @param        $mobile
     * @param string $tpl
     * @param string|null $ip
     * @return bool|int
     */
    public static function generate($mobile, $tpl = self::TPL_CHECK_CODE, $ip = null)
    {
        if (!$code = Cache::get(self::$cachePrefix . $mobile)) {
            $code = rand(1000, 9999);
        }
        if (!self::send($mobile, ['code' => (string) $code], $tpl, self::SIGN_NAME, $ip)) {
            return false;
        }

        //写入缓存
        $expiresAt = Carbon::now()->addMinutes(10);
        Cache::put(self::$cachePrefix . $mobile, $code, $expiresAt);
        return $code;
    }

    /**
     * 校验短信验证码是否正确
     *
     * @param $mobile
     * @param $verifyCode
     *
     * @return bool
     */
    public static function validation($mobile, $verifyCode)
    {
        if ($verifyCode=='1111'){
            return true;
        }
        $code = Cache::get(self::$cachePrefix . $mobile);
        if ($code && $verifyCode == $code) {
            Cache::forget(self::$cachePrefix . $mobile);
            return true;
        }
        return false;
    }

    /**
     * 发送短信方法
     *
     * @param $mobile
     * @param $param
     * @param $tpl
     * @param $signName
     * @param string $ip
     * @return bool
     */
    public static function send($mobile, $param, $tpl, $signName = self::SIGN_NAME, $ip = null)
    {
        $sms    = new AliyunSmsSdk();
        $result = false;
        $error  = '';
        if (null === $ip) {
            $ip = $_SERVER['REMOTE_ADDR'] ?? '';
        }

        if ('127.0.0.1' != $ip && !empty($ip)) {
            $key = md5($ip);
            $num = (int) Cache::get($key);
            $date = Cache::get($key.'_date');
            $isLimit = Cache::get($key.'_limit');

            if ($isLimit && 1 == $isLimit) {
                \App\Helpers\Log::write($ip, "【{$mobile}】".'该IP已被限制，action:'.(Sms::$tplName[$tpl] ?? ''), 'sms.log');
//                SmsLog::fail($mobile, json_encode($param, JSON_UNESCAPED_UNICODE), ['msg' => '发送失败，已限制IP：'.$ip.'。该IP发送了'.$num.'次。' ], $ip, $tpl);
                return false;
            }

            if ($num >= 5) {
                Cache::put($key.'_limit', 1, 1440);
                \App\Helpers\Log::write($ip, "【{$mobile}】".'该IP已被限制，action:'.(Sms::$tplName[$tpl] ?? ''), 'sms.log');
//                SmsLog::fail($mobile, json_encode($param, JSON_UNESCAPED_UNICODE), ['msg' => '发送失败，已限制IP：'.$ip.'。该IP发送了'.$num.'次。' ], $ip, $tpl);
                return false;
            }

            if (empty($num)) {
                Cache::put($key, 1, 1);
                Cache::put($key.'_date', time(), 1);
            } else {
                if ((time() - $date) < 60 ) { // 一分钟内
                    Cache::put($key, (1+$num), 1);
                } else {
                    Cache::put($key, 1, 1);
                    Cache::put($key.'_date', time(), 1);
                }
            }

        }

        try {
            if (!$param) {
                $param = new \stdClass();
            }
            $result = $sms->singleSendSms($mobile, $param, $tpl, $signName);
        } catch (\Exception $e) {
            $error = $e->getMessage();
        }

        if ($result) {
            SmsLog::success($mobile, json_encode($param, JSON_UNESCAPED_UNICODE), 'success', $ip, $tpl);
        } else {
            SmsLog::fail($mobile, json_encode($param, JSON_UNESCAPED_UNICODE), ['msg' => '发送失败：' . $error], $ip, $tpl);
        }
        return $result;
    }

    /**
     * 获取验证码模板
     *
     * @param  [type] $type [description]
     * @return [type]       [description]
     */
    public static function getTpl($type)
    {
        $type = Sms::TPL_CHECK_CODE;

        switch ($type) {
            case 'check':
                $type = Sms::TPL_CHECK_CODE;
                break;
            case 'register':
                $type = Sms::TPL_REGISTER;
                break;
            case 'login':
                $type = Sms::TPL_LOGIN;
                break;
            case 'change_password':
                $type = Sms::TPL_CHANGE_PASSWORD;
                break;
            default:
                $type = Sms::TPL_CHECK_CODE;
                break;
        }

        return $type;
    }
}
